# encoding: utf-8
"""
@author: 夏洛
@QQ: 1972386194
@file: 易盾.py
"""


'''
打开网页
点击 滑块  点击嵌入式
获取图片地址  
进行比对  找到缺口位置
构造移动轨迹
进行拖动

'''


from selenium import webdriver
import re
import time
import random
import cv2
import requests
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains


chrome_options = Options()
chrome_options.add_argument('--headless')
url = 'https://dun.163.com/trial/jigsaw'
driver = webdriver.Chrome()
driver.get(url)
WebDriverWait(driver, 5).until(EC.title_contains("滑动拼图"))
driver.maximize_window()
em = driver.find_element_by_xpath('//ul[@class="tcapt-tabs__container"]/li[2]')
em.click()
driver.execute_script('window.scrollTo(0, 300)')

time.sleep(1)
html = driver.page_source
bg_img = re.findall(r'alt="验证码背景".*?src="(.*?)"', html)[0]
hk_img = re.findall(r'alt="验证码滑块".*?src="(.*?)"', html)[0]
print(bg_img)
print(hk_img)

def save_img():
    with open('./images/bg.jpg', 'wb') as f:
        f.write(requests.get(bg_img).content)
        f.close()

    with open('./images/hk.png', 'wb') as f:
        f.write(requests.get(hk_img).content)
        f.close()

def get_distance():
    """
    获取移动距离
    :return:
    """

    # 读取背景图片和缺口图片
    bg_img = cv2.imread('./images/bg.jpg')  # 背景图片
    tp_img = cv2.imread('./images/hk.png')  # 缺口图片
    # 识别图片边缘
    bg_edge = cv2.Canny(bg_img, 100, 200)
    tp_edge = cv2.Canny(tp_img, 100, 200)
    # 转换图片格式
    bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
    tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
    # 缺口匹配
    res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  # 寻找最优匹配
    x = max_loc[0]  # 滑块在验证图片的x坐标（左边）
    # 绘制方框
    th, tw = tp_pic.shape[:2]
    tl = max_loc  # 左上角点的坐标
    print(tl)
    br = (tl[0] + tw, tl[1] + th)  # 右下角点的坐标
    print(br)
    print(br[0])
    cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2)  # 绘制矩形
    cv2.imwrite('./images/out.jpg', bg_img)  # 保存在本地
    # 滑块的宽度方形框40个像素，再加上红色矩形框的2个像素
    return int(br[0]) - 43

def track(distance):
    """
    规划移动的轨迹

    :param distance:
    :return:
    """
    # 匀速移动
    # for i in range(distance):
    #     ActionChains(self.driver).move_by_offset(1, 0).perform()
    # ActionChains(self.driver).move_by_offset(distance-5, 0).perform()
    t = 0.1
    speed = 0
    current = 0
    mid = 3 / 5 * distance
    track_list = []
    while current < distance:
        if current < mid:
            a = random.choice([1, 2, 3])
            # a = 3
        else:
            a = random.choice([-1, -2, -3])
            # a = -4
        move_track = speed * t + 0.5 * a * t ** 2
        track_list.append(round(move_track))
        speed = speed + a * t
        current += move_track
    # 模拟人类来回移动了一小段
    end_track = [1, 0] * 10 + [0] * 10 + [-1, 0] * 10
    track_list.extend(end_track)
    offset = sum(track_list) - distance
    # 由于四舍五入带来的误差,这里需要补回来
    if offset > 0:
        track_list.extend(offset * [-1, 0])
    elif offset < 0:
        track_list.extend(offset * [1, 0])
    return track_list

def slid_button(distance):
    """
    根据缺口位置，移动滑块特定的距离distance
    :param diatance:
    :return:
    """
    # 获取滑块元素
    button = driver.find_element_by_xpath('//div[@class="yidun_slider"]/span')
    # /html/body/main/div[1]/div/div[2]/div[2]/div[1]/div[2]/div/div/div[2]/div[3]/div/div/div[2]/div[2]/span
    ActionChains(driver).click_and_hold(button).perform()
    time.sleep(0.5)
    track_list = track(distance - 3)
    for i in track_list:
        ActionChains(driver).move_by_offset(i, 0).perform()
    time.sleep(1)
    # 放开鼠标
    ActionChains(driver).release().perform()


if __name__ == '__main__':
    save_img()
    distance = get_distance()
    slid_button(distance)
    time.sleep(5)
    driver.close()
